from typing import Dict, Any
from .base_agent import BaseAgent
from utils import logger, TestRunner

class TesterAgent(BaseAgent):
    """测试工程师代理 - 负责生成和执行测试用例"""
    
    def __init__(self):
        super().__init__(
            name="测试工程师",
            role="质量保证工程师和测试专家"
        )
        self.test_runner = TestRunner()
    
    def _get_system_prompt(self) -> str:
        return """你是一个专业的测试工程师，具有以下专业技能：

🔍 **测试技能**：
- 单元测试、集成测试、系统测试
- 测试驱动开发（TDD）和行为驱动开发（BDD）
- 自动化测试框架（pytest、unittest、selenium）
- 性能测试和压力测试
- 安全测试和代码覆盖率分析

📋 **测试策略**：
- 边界值测试
- 等价类划分
- 异常路径测试
- 回归测试
- 测试用例设计

🛠️ **工具使用**：
- pytest、unittest、nose等测试框架
- mock和fixture设计
- 测试数据管理
- 持续集成测试

✅ **质量标准**：
- 代码覆盖率 > 80%
- 测试用例可读性和可维护性
- 测试报告和缺陷跟踪
- 性能基准和回归检测

请生成全面、可靠的测试代码，确保软件质量。用中文注释。"""
    
    def process(self, input_data: Dict[str, Any]) -> Dict[str, Any]:
        """生成并执行测试用例"""
        generated_code = input_data.get('generated_code', '')
        code_files = input_data.get('code_files', {})
        architecture_design = input_data.get('architecture_design', '')
        
        if not generated_code and not code_files:
            return {
                'success': False,
                'error': '未提供生成的代码'
            }
        
        # 如果没有解析的代码文件，尝试从生成的代码中解析
        if not code_files and generated_code:
            code_files = {'main.py': generated_code}
        
        # 构造测试生成提示
        prompt = f"""
基于以下代码生成完整的测试套件：

**架构设计**：
{architecture_design}

**代码文件**：
{self._format_code_files(code_files)}

**请生成测试代码，要求**：

## 1. 测试覆盖
- 为每个函数和类生成单元测试
- 包含正常情况和异常情况测试
- 边界值测试和极端情况测试
- 集成测试（如果有多个模块）

## 2. 测试框架
- 使用pytest框架
- 合理使用fixture和参数化测试
- Mock外部依赖
- 设置teardown清理

## 3. 测试结构
每个测试文件用以下格式分隔：

```python
# === 测试文件: 文件路径 ===
# 测试说明

测试代码...
```

## 4. 测试质量
- 测试用例命名清晰（test_功能_场景_期望结果）
- 遵循AAA模式（Arrange、Act、Assert）
- 包含详细的中文注释
- 断言清晰明确

## 5. 特殊测试
- 性能测试（如果适用）
- 安全测试（输入验证）
- 错误处理测试
- 配置测试

请生成完整的测试套件。
"""
        
        try:
            test_code = self._call_llm(prompt)
            test_files = self._parse_test_files(test_code)
            
            # 执行测试（如果可能）
            test_results = {}
            overall_success = True
            
            for test_file, test_content in test_files.items():
                try:
                    # 这里可以实际执行测试，为简化起见，我们模拟测试结果
                    result = self._simulate_test_execution(test_content)
                    test_results[test_file] = result
                    if not result['passed']:
                        overall_success = False
                except Exception as e:
                    test_results[test_file] = {
                        'passed': False,
                        'error': str(e),
                        'coverage': 0
                    }
                    overall_success = False
            
            return {
                'success': True,
                'test_code': test_code,
                'test_files': test_files,
                'test_results': test_results,
                'overall_test_success': overall_success,
                'summary': f'测试生成完成，共生成{len(test_files)}个测试文件'
            }
            
        except Exception as e:
            logger.error(f"测试生成失败: {e}")
            return {
                'success': False,
                'error': str(e),
                'summary': '测试生成失败'
            }
    
    def _format_code_files(self, code_files: Dict[str, str]) -> str:
        """格式化代码文件为字符串"""
        formatted = ""
        for file_path, content in code_files.items():
            formatted += f"\n--- {file_path} ---\n{content}\n"
        return formatted
    
    def _parse_test_files(self, test_code: str) -> Dict[str, str]:
        """解析测试代码，分离不同文件"""
        files = {}
        lines = test_code.split('\n')
        current_file = None
        current_content = []
        
        for line in lines:
            if line.strip().startswith('# === 测试文件:') and line.strip().endswith('==='):
                # 保存上一个文件
                if current_file and current_content:
                    files[current_file] = '\n'.join(current_content)
                
                # 开始新文件
                current_file = line.strip().replace('# === 测试文件:', '').replace('===', '').strip()
                current_content = []
            else:
                if current_file:
                    current_content.append(line)
        
        # 保存最后一个文件
        if current_file and current_content:
            files[current_file] = '\n'.join(current_content)
        
        # 如果没有找到文件分隔符，将整个内容作为单个文件
        if not files:
            files['test_main.py'] = test_code
        
        return files
    
    def _simulate_test_execution(self, test_content: str) -> Dict[str, Any]:
        """模拟测试执行（实际项目中应该真正执行测试）"""
        # 统计测试函数数量
        test_count = test_content.count('def test_')
        
        # 模拟测试结果
        return {
            'passed': True,  # 在实际项目中这应该是真实的测试结果
            'test_count': test_count,
            'failures': 0,
            'coverage': 85.5,  # 模拟覆盖率
            'execution_time': 0.123
        }
    
    def generate_performance_tests(self, code: str) -> str:
        """生成性能测试"""
        prompt = f"""
为以下代码生成性能测试：

```python
{code}
```

要求：
1. 使用pytest-benchmark进行性能测试
2. 测试关键函数的执行时间
3. 内存使用情况测试
4. 并发性能测试（如果适用）
5. 设置性能基准和回归检测

请提供完整的性能测试代码。
"""
        
        return self._call_llm(prompt)
    
    def generate_integration_tests(self, code_files: Dict[str, str]) -> str:
        """生成集成测试"""
        code_summary = self._format_code_files(code_files)
        
        prompt = f"""
为以下多模块系统生成集成测试：

{code_summary}

要求：
1. 测试模块间的交互
2. 端到端功能测试
3. 数据流测试
4. 配置集成测试
5. 错误传播测试

请提供完整的集成测试套件。
"""
        
        return self._call_llm(prompt) 